package org.Yiran.timetale_re.client.gui.overlay;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.client.gui.overlay.ForgeGui;
import net.minecraftforge.client.gui.overlay.IGuiOverlay;
import org.Yiran.timetale_re.capability.RuneCraftingProficiency;
import org.Yiran.timetale_re.capability.RuneCraftingProficiencyProvider;

/**
 * 符文制作熟练度覆盖层类
 * 用于在游戏界面中显示玩家的符文制作等级和经验信息
 * 支持淡入淡出效果和多种显示位置
 */
public class RuneProficiencyOverlay implements IGuiOverlay {
    
    // ==================== 位置枚举定义 ====================

    /**
     * 覆盖层显示位置枚举
     * 定义了9种可能的显示位置
     */
    public enum OverlayPosition {
        TOP_LEFT,      // 左上角
        TOP_CENTER,    // 顶部居中
        TOP_RIGHT,     // 右上角
        CENTER_LEFT,   // 左侧居中
        CENTER,        // 屏幕中心
        CENTER_RIGHT,  // 右侧居中
        BOTTOM_LEFT,   // 左下角
        BOTTOM_CENTER, // 底部居中
        BOTTOM_RIGHT   // 右下角
    }

    // ==================== 显示控制常量 ====================
    
    /** 显示持续时间(2.5秒) */
    private static final long DISPLAY_DURATION = 2500;
    
    /** 淡入淡出速度 */
    private static final float FADE_SPEED = 0.05f;

    // ==================== 显示控制变量 ====================

    /** 当前显示位置，默认为右上角 */
    private OverlayPosition currentPosition = OverlayPosition.TOP_RIGHT;

    /** 上次变化时间戳 */
    private long lastChangeTime = 0;
    
    /** 上次记录的等级 */
    private int lastLevel = -1;
    
    /** 上次记录的经验值 */
    private double lastExperience = -1.0;
    
    /** 当前透明度(0-1) */
    private float alpha = 0.0f;

    // ==================== 主要渲染方法 ====================

    /**
     * 渲染覆盖层的主要方法
     *
     * @param gui Forge GUI实例
     * @param guiGraphics GUI图形绘制对象
     * @param partialTick 部分刻度(用于平滑动画)
     * @param screenWidth 屏幕宽度
     * @param screenHeight 屏幕高度
     */
    @Override
    public void render(ForgeGui gui, GuiGraphics guiGraphics, float partialTick, int screenWidth, int screenHeight) {
        Minecraft mc = Minecraft.getInstance();
        Player player = mc.player;

        // 基本条件检查：玩家存在、非调试模式、无其他屏幕显示时才渲染
        if (player == null || mc.options.renderDebug || mc.screen != null) {
            return;
        }

        // 获取玩家的制符熟练度并渲染信息
        player.getCapability(RuneCraftingProficiencyProvider.RUNE_CRAFTING_PROFICIENCY).ifPresent(proficiency -> {
            // 只有当玩家的制符等级大于0或经验值大于0时才显示
            if (proficiency.getProficiencyLevel() > 0 || proficiency.getExperience() > 0) {
                updateVisibility(proficiency);  // 更新显示状态
                if (alpha > 0) {  // 只有当透明度大于0时才渲染
                    renderProficiencyInfo(guiGraphics, mc.font, proficiency, screenWidth, screenHeight);
                }
            }
        });
    }

    // ==================== 显示状态控制方法 ====================

    /**
     * 更新显示状态（淡入淡出逻辑）
     * 根据熟练度变化控制覆盖层的显示和隐藏
     *
     * @param proficiency 符文制作熟练度能力实例
     */
    private void updateVisibility(RuneCraftingProficiency proficiency) {
        // 检查熟练度是否为初始状态（0级0经验），如果是则不显示
        if (proficiency.getProficiencyLevel() == 0 && proficiency.getExperience() == 0.0) {
            // 如果当前是显示状态，则开始淡出
            if (alpha > 0.0f) {
                alpha = Math.max(0.0f, alpha - FADE_SPEED);
            }
            return;
        }

        // 检查熟练度是否发生变化
        int currentLevel = proficiency.getProficiencyLevel();
        double currentExperience = proficiency.getExperience();

        // 如果等级或经验发生变化，更新最后变化时间和记录值
        if (currentLevel != lastLevel || currentExperience != lastExperience) {
            lastChangeTime = System.currentTimeMillis();
            lastLevel = currentLevel;
            lastExperience = currentExperience;
        }

        // 检查是否应该显示（距离上次变化时间小于显示持续时间）
        boolean shouldDisplay = (System.currentTimeMillis() - lastChangeTime) < DISPLAY_DURATION;

        // 更新透明度（淡入淡出）
        if (shouldDisplay && alpha < 1.0f) {
            // 淡入：逐渐增加透明度至1.0
            alpha = Math.min(1.0f, alpha + FADE_SPEED);
        } else if (!shouldDisplay && alpha > 0.0f) {
            // 淡出：逐渐减少透明度至0.0
            alpha = Math.max(0.0f, alpha - FADE_SPEED);
        }
    }

    // ==================== 信息渲染方法 ====================

    /**
     * 渲染熟练度信息
     * 绘制等级、经验和经验条等UI元素
     *
     * @param guiGraphics GUI图形绘制对象
     * @param font 字体渲染器
     * @param proficiency 符文制作熟练度能力实例
     * @param screenWidth 屏幕宽度
     * @param screenHeight 屏幕高度
     */
    private void renderProficiencyInfo(GuiGraphics guiGraphics, Font font, RuneCraftingProficiency proficiency, int screenWidth, int screenHeight) {
        // 获取熟练度信息
        int level = proficiency.getProficiencyLevel();
        double experience = proficiency.getExperience();
        double expToNext = proficiency.getExperienceToNextLevel();

        // 创建显示文本
        String levelText = "制符等级: " + level;
        String expText = String.format("经验: %.0f/%.0f", experience, experience + expToNext);

        // 计算文本宽度，用于布局计算
        int levelWidth = font.width(levelText);
        int expWidth = font.width(expText);
        int barWidth = Math.max(levelWidth, expWidth);

        // 使用新方法计算位置
        int[] position = calculatePosition(screenWidth, screenHeight, barWidth);
        int barX = position[0];
        int y = position[1];

        // 计算基于alpha的透明度值
        int backgroundColor = (int) (0x80 * alpha) << 24; // 半透明黑色背景
        int textColor = (int) (0xFF * alpha) << 24 | 0xFFFFFF; // 白色文字
        int grayTextColor = (int) (0xAA * alpha) << 24 | 0xAAAAAA; // 灰色文字
        int barBgColor = (int) (0xFF * alpha) << 24 | 0xFF555555; // 经验条背景
        int barFgColor = (int) (0xFF * alpha) << 24 | 0xFF55FF55; // 经验条前景

        // 绘制半透明背景
        int bgX = barX - 6;
        int bgY = y - 2;
        int bgWidth = barWidth + 12;
        int bgHeight = 24;

        // 绘制背景矩形
        guiGraphics.fill(bgX, bgY, bgX + bgWidth, bgY + bgHeight, backgroundColor);

        // 绘制文本
        guiGraphics.drawString(font, levelText, barX, y, textColor);
        guiGraphics.drawString(font, expText, barX, y + 12, grayTextColor);

        // 绘制经验条
        int barY = y + 26;
        int barHeight = 4;

        // 经验条背景
        guiGraphics.fill(barX, barY, barX + barWidth, barY + barHeight, barBgColor);

        // 经验条前景
        float expPercent = (float) (experience / (experience + expToNext));
        int expBarWidth = (int) (barWidth * expPercent);
        guiGraphics.fill(barX, barY, barX + expBarWidth, barY + barHeight, barFgColor);
    }

    // ==================== 位置计算方法 ====================

    /**
     * 根据当前位置设置计算渲染位置
     *
     * @param screenWidth  屏幕宽度
     * @param screenHeight 屏幕高度
     * @param contentWidth 内容宽度
     * @return 包含[x, y]坐标的数组
     */
    private int[] calculatePosition(int screenWidth, int screenHeight, int contentWidth) {
        int margin = 10; // 边距
        int x = 0;
        int y = switch (currentPosition) {
            case TOP_LEFT -> {
                x = margin;
                yield margin;
            }
            case TOP_CENTER -> {
                x = (screenWidth - contentWidth) / 2;
                yield margin;
            }
            case TOP_RIGHT -> {
                x = screenWidth - contentWidth - margin;
                yield margin;
            }
            case CENTER_LEFT -> {
                x = margin;
                yield (screenHeight - 30) / 2;
            }
            case CENTER -> {
                x = (screenWidth - contentWidth) / 2;
                yield (screenHeight - 30) / 2;
            }
            case CENTER_RIGHT -> {
                x = screenWidth - contentWidth - margin;
                yield (screenHeight - 30) / 2;
            }
            case BOTTOM_LEFT -> {
                x = margin;
                yield screenHeight - 30 - margin;
            }
            case BOTTOM_CENTER -> {
                x = (screenWidth - contentWidth) / 2;
                yield screenHeight - 30 - margin;
            }
            case BOTTOM_RIGHT -> {
                x = screenWidth - contentWidth - margin;
                yield screenHeight - 30 - margin;
            }
        };

        // 根据当前设置的位置枚举计算具体的屏幕坐标

        return new int[]{x, y};
    }

    // ==================== 位置控制方法 ====================

    /**
     * 设置覆盖层的位置
     *
     * @param position 期望的位置
     */
    public void setPosition(OverlayPosition position) {
        this.currentPosition = position;
    }

    /**
     * 获取当前覆盖层的位置
     *
     * @return 当前位置
     */
    public OverlayPosition getPosition() {
        return this.currentPosition;
    }
}